package com.demon.framework.util.serialize;

import com.google.common.collect.Lists;
import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;
import org.springframework.core.serializer.support.SerializationFailedException;
import org.springframework.util.Assert;
import org.springframework.util.Base64Utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;

/**
 * @author Demon-HY
 * @date 2020-7-23
 */
public class ProtostuffUtil {

    public static <T> String serializeToBase64(T obj) {
        return Base64Utils.encodeToString(serialize(obj));
    }

    public static <T> T deserializeFromBase64(String paramStrOfBase64ForByte, Class<T> targetClass) {
        return deserialize(Base64Utils.decodeFromString(paramStrOfBase64ForByte), targetClass);
    }

    public static <T> byte[] serialize(T obj) {
        return serializeList(Lists.newArrayList(obj));
    }

    public static <T> T deserialize(byte[] paramArrayOfByte, Class<T> targetClass) {
        return deserializeList(paramArrayOfByte, targetClass).get(0);
    }

    public static <T> byte[] serializeList(List<T> objList) {
        Assert.notEmpty(objList, "序列化对象不能为空");

        Schema<T> schema = (Schema<T>) RuntimeSchema.getSchema(objList.get(0).getClass());
        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            ProtostuffIOUtil.writeListTo(bos, objList, schema, buffer);
            return bos.toByteArray();
        } catch (Exception e) {
            throw new SerializationFailedException("序列化对象列表(" + objList + ")发生异常!", e);
        } finally {
            buffer.clear();
        }

    }

    public static <T> List<T> deserializeList(byte[] paramArrayOfByte, Class<T> targetClass) {
        Assert.notNull(paramArrayOfByte, "反序列化byte不能为空");
        Assert.notNull(targetClass, "反序列化类不能为空");


        Schema<T> schema = RuntimeSchema.getSchema(targetClass);
        try {
            return ProtostuffIOUtil.parseListFrom(new ByteArrayInputStream(paramArrayOfByte), schema);
        } catch (IOException e) {
            throw new SerializationFailedException("反序列化对象列表发生异常!", e);
        }

    }

}
